FrameLib  2.0
DSP processing with frames of arbitrary timing and length
FrameLib_Multistream.h
Go to the documentation of this file.
1 
2 #ifndef FRAMELIB_MULTISTREAM_H
3 #define FRAMELIB_MULTISTREAM_H
4 
5 #include "FrameLib_Types.h"
6 #include "FrameLib_Context.h"
7 #include "FrameLib_Object.h"
8 #include "FrameLib_DSP.h"
9 
10 #include <algorithm>
11 #include <vector>
12 
29 class FrameLib_Multistream : public FrameLib_Object<FrameLib_Multistream>
30 {
31 
32 protected:
33 
35  using MultistreamOutput = std::vector<BlockConnection>;
37 
38 public:
39 
40  virtual const FrameLib_Parameters::Serial *getSerialised() = 0;
41 
42  // Constructors
43 
44  FrameLib_Multistream(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, unsigned long nStreams, unsigned long nIns, unsigned long nOuts)
45  : FrameLib_Object(type, context, proxy), mNumStreams(nStreams)
46  { setIO(nIns, nOuts); }
47 
48  FrameLib_Multistream(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, unsigned long nStreams)
49  : FrameLib_Object(type, context, proxy), mNumStreams(nStreams) {}
50 
51  // Destructor
52 
53  virtual ~FrameLib_Multistream() {}
54 
55  // Non-copyable
56 
59 
60  // Default is not to handle audio
61 
62  static bool handlesAudio() { return false; }
63 
64  // Number of Streams
65 
66  unsigned long getNumStreams() { return mNumStreams; }
67 
68 protected:
69 
70  // IO Utilities
71 
72  // Call this in derived class constructors if the IO size is not always the same
73 
74  void setIO(unsigned long nIns, unsigned long nOuts, unsigned long nAudioChans = 0)
75  {
76  FrameLib_Object::setIO(nIns, nOuts, nAudioChans);
77  mOutputs.resize(getNumOuts());
78  }
79 
80  // Query Connections for Individual Channels
81 
82  unsigned long getInputNumChans(unsigned long inIdx);
83  BlockConnection getInputChan(unsigned long inIdx, unsigned long chan);
84 
85  unsigned long getOrderingConnectionNumChans(unsigned long idx);
86  BlockConnection getOrderingConnectionChan(unsigned long idx, unsigned long chan);
87 
88 private:
89 
90  // Connection Methods (private)
91 
92  void connectionUpdate(Queue *queue) final
93  {
94  if (inputUpdate())
95  outputUpdate(queue);
96  }
97 
98  virtual bool inputUpdate() = 0;
99  void outputUpdate(Queue *queue);
100 
101 protected:
102 
103  // Outputs
104 
105  std::vector<MultistreamOutput> mOutputs;
106 
107 private:
108 
109  unsigned long mNumStreams;
110 };
111 
112 
123 template <class T>
125 {
126 
127 public:
128 
129  const FrameLib_Parameters::Serial *getSerialised() override { return &mSerialisedParameters; }
130 
131  FrameLib_Expand(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy, unsigned long nStreams)
132  : FrameLib_Multistream(T::getType(), context, proxy, nStreams), mSerialisedParameters(serialisedParameters->size())
133  {
134  // Make first block
135 
136  mBlocks.add(new T(context, serialisedParameters, proxy));
137  mBlocks[0]->setStream(this, 0);
138 
139  // Copy serialised parameters for later instantiations
140 
141  mSerialisedParameters.write(serialisedParameters);
142 
143  // Set up IO / fixed inputs / audio temps
144 
145  setIO(mBlocks[0]->getNumIns(), mBlocks[0]->getNumOuts(), getNumStreams() * mBlocks[0]->getNumAudioChans());
146  mFixedInputs.resize(getNumIns());
147  mAudioTemps.resize(mBlocks[0]->getNumAudioOuts());
148 
149  // Make initial output connections
150 
151  for (unsigned long i = 0; i < getNumOuts(); i++)
152  mOutputs[i].push_back(BlockConnection(mBlocks[0].get(), i));
153 
154  // Check for ordering support
155 
156  if (mBlocks[0]->supportsOrderingConnections())
158 
159  reset(0.0, 4096);
160  }
161 
162  // Fixed Inputs
163 
164  void setFixedInput(unsigned long idx, double *input, unsigned long size) override
165  {
166  if (idx < mFixedInputs.size())
167  {
168  mFixedInputs[idx].assign(input, input + size);
169  updateFixedInput(idx);
170  }
171  }
172 
173  const double *getFixedInput(unsigned long idx, unsigned long *size) override
174  {
175  return mBlocks[0]->getFixedInput(idx, size);
176  }
177 
178  // Audio Processing
179 
180  void blockUpdate(const double * const *ins, double **outs, unsigned long blockSize) override
181  {
182  unsigned long internalNumIns = mBlocks[0]->getNumAudioIns();
183  unsigned long internalNumOuts = mBlocks[0]->getNumAudioOuts();
184 
185  // Allocate temporary memory
186 
187  if (internalNumOuts)
188  mAudioTemps[0] = alloc<double>(blockSize * internalNumOuts);
189  for (unsigned long i = 1; i < internalNumOuts; i++)
190  mAudioTemps[i] = mAudioTemps[0] + (i * blockSize);
191 
192  // Zero outputs
193 
194  for (unsigned long i = 0; i < getNumAudioOuts(); i++)
195  std::fill_n(outs[i], blockSize, 0.0);
196 
197  // Process and sum to outputs
198 
199  for (unsigned long i = 0; i < mBlocks.size(); i++)
200  {
201  unsigned long inStreamOffset = internalNumIns * (i % getNumStreams());
202  unsigned long outStreamOffset = internalNumOuts * (i % getNumStreams());
203 
204  mBlocks[i]->blockUpdate(ins + inStreamOffset, mAudioTemps.data(), blockSize);
205 
206  for (unsigned long j = 0; j < internalNumOuts; j++)
207  for (unsigned long k = 0; k < blockSize; k++)
208  outs[outStreamOffset + j][k] += mAudioTemps[j][k];
209  }
210 
211  // Release temporary memory and clear allocator
212 
213  if (getNumAudioOuts())
214  dealloc(mAudioTemps[0]);
215 
216  clearAllocator();
217  }
218 
219  // Reset
220 
221  void reset(double samplingRate, unsigned long maxBlockSize) override
222  {
223  mSamplingRate = samplingRate;
224  mMaxBlockSize = maxBlockSize;
225 
226  for (auto it = mBlocks.begin(); it != mBlocks.end(); it++)
227  (*it)->reset(samplingRate, maxBlockSize);
228  }
229 
230  // Handles Audio
231 
232  static bool handlesAudio() { return T::handlesAudio(); }
233 
234  // Info
235 
236  std::string objectInfo(bool verbose) override { return mBlocks[0]->objectInfo(verbose); }
237  std::string inputInfo(unsigned long idx, bool verbose) override { return mBlocks[0]->inputInfo(idx, verbose); }
238  std::string outputInfo(unsigned long idx, bool verbose) override { return mBlocks[0]->outputInfo(idx, verbose); }
239 
240  std::string audioInfo(unsigned long idx, bool verbose) override
241  {
242  return formatInfo((mBlocks[0]->audioInfo(idx % mBlocks[0]->getNumAudioChans(), verbose) + " [#]").c_str(), idx / mBlocks[0]->getNumAudioChans());
243  }
244 
245  FrameType inputType(unsigned long idx) const override { return mBlocks[0]->inputType(idx); }
246  FrameType outputType(unsigned long idx) const override { return mBlocks[0]->outputType(idx); }
247 
248  const FrameLib_Parameters *getParameters() const override { return mBlocks[0]->getParameters(); }
249 
250  // Ordering Connections
251 
252  void autoOrderingConnections() override
253  {
254  for (auto it = mBlocks.begin(); it != mBlocks.end(); it++)
255  (*it)->autoOrderingConnections();
256  }
257 
259  {
260  for (auto it = mBlocks.begin(); it != mBlocks.end(); it++)
261  (*it)->clearAutoOrderingConnections();
262  }
263 
264 private:
265 
266  // Update Fixed Inputs
267 
268  void updateFixedInput(unsigned long idx)
269  {
270  for (unsigned long i = 0; i < mBlocks.size(); i++)
271  mBlocks[i]->setFixedInput(idx, mFixedInputs[idx].data(), mFixedInputs[idx].size());
272  }
273 
274  // Update (expand)
275 
276  bool inputUpdate() override
277  {
278  // Find number of channels (always keep at least one channel)
279 
280  unsigned long nChannels = 1;
281  unsigned long cChannels = mBlocks.size();
282 
283  for (unsigned long i = 0; i < getNumIns(); i++)
284  if (getInputNumChans(i) > nChannels)
285  nChannels = getInputNumChans(i);
286 
287  nChannels = std::max(nChannels, getNumStreams());
288 
289  // Resize if necessary
290 
291  bool numChansChanged = nChannels != cChannels;
292 
293  if (numChansChanged)
294  {
295  // Change the number of hosted blocks
296 
297  if (nChannels > cChannels)
298  {
299  for (unsigned long i = cChannels; i < nChannels; i++)
300  {
301  mBlocks.add(new T(getContext(), &mSerialisedParameters, getProxy()));
302  mBlocks.back()->setStream(this, i);
303  mBlocks.back()->reset(mSamplingRate, mMaxBlockSize);
304  }
305  }
306  else
307  mBlocks.resize(nChannels);
308 
309  // Redo output connection lists
310 
311  for (unsigned long i = 0; i < getNumOuts(); i++)
312  mOutputs[i].clear();
313 
314  for (unsigned long i = 0; i < getNumOuts(); i++)
315  for (unsigned long j = 0; j < nChannels; j++)
316  mOutputs[i].push_back(BlockConnection(mBlocks[j].get(), i));
317 
318  // Update Fixed Inputs
319 
320  for (unsigned long i = 0; i < getNumIns(); i++)
321  updateFixedInput(i);
322  }
323 
324  // Make input connections
325 
326  for (unsigned long i = 0; i < getNumIns(); i++)
327  {
328  if (getInputNumChans(i))
329  {
330  for (unsigned long j = 0; j < nChannels; j++)
331  mBlocks[j]->addConnection(getInputChan(i, j % getInputNumChans(i)), i);
332  }
333  else
334  {
335  for (unsigned long j = 0; j < nChannels; j++)
336  mBlocks[j]->deleteConnection(i);
337  }
338  }
339 
340  // Clear ordering connections
341 
342  for (unsigned long j = 0; j < nChannels; j++)
343  mBlocks[j]->clearOrderingConnections();
344 
345  // Make ordering connections
346 
347  for (unsigned long i = 0; i < getNumOrderingConnections(); i++)
348  {
350  for (unsigned long j = 0; j < nChannels; j++)
352  }
353 
354  return numChansChanged;
355  }
356 
357  // Member Variables
358 
359  FrameLib_Parameters::AutoSerial mSerialisedParameters;
360 
362  std::vector<std::vector<double>> mFixedInputs;
363 
364  unsigned long mMaxBlockSize;
365  double mSamplingRate;
366 
367  std::vector<double *> mAudioTemps;
368 };
369 
370 #endif
ObjectType
Definition: FrameLib_Types.h:53
holds the connected object and IO indices for a connection to an object
Definition: FrameLib_Object.h:143
void deleteConnection(unsigned long inIdx)
Definition: FrameLib_Object.h:260
static bool handlesAudio()
Definition: FrameLib_Multistream.h:62
ConnectionResult addOrderingConnection(Connection connection)
Definition: FrameLib_Object.h:265
const FrameLib_Parameters * getParameters() const override
Definition: FrameLib_Multistream.h:248
unsigned long getNumOuts() const
Definition: FrameLib_Object.h:217
a set of parameters for a FrameLib object.
Definition: FrameLib_Parameters.h:30
FrameLib_Proxy * getProxy() const
Definition: FrameLib_Object.h:212
void clearAutoOrderingConnections() override
Definition: FrameLib_Multistream.h:258
BlockConnection getInputChan(unsigned long inIdx, unsigned long chan)
Definition: FrameLib_Multistream.cpp:15
a class used to represent distinct non-connectable areas in the host environment. ...
Definition: FrameLib_Context.h:21
FrameLib_Expand(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy, unsigned long nStreams)
Definition: FrameLib_Multistream.h:131
static bool handlesAudio()
Definition: FrameLib_Multistream.h:232
a set of tagged parameter values using external non-owned memory.
Definition: FrameLib_Parameters.h:51
void dealloc(U *&ptr)
Definition: FrameLib_Object.h:400
unsigned long getInputNumChans(unsigned long inIdx)
Definition: FrameLib_Multistream.cpp:8
unsigned long getNumAudioChans() const
Definition: FrameLib_Object.h:220
a virtual struct allowing for extensible communication to/from the host environment.
Definition: FrameLib_Types.h:69
ObjectType getType() const
Definition: FrameLib_Object.h:204
void setIO(unsigned long nIns, unsigned long nOuts, unsigned long nAudioChans=0)
Definition: FrameLib_Multistream.h:74
std::vector< BlockConnection > MultistreamOutput
Definition: FrameLib_Multistream.h:35
std::vector< MultistreamOutput > mOutputs
Definition: FrameLib_Multistream.h:105
an abstract template class providing an interface for FrameLib objects and implementing connectivity ...
Definition: FrameLib_Object.h:128
virtual void setFixedInput(unsigned long idx, double *input, unsigned long size)=0
void reset(double samplingRate, unsigned long maxBlockSize) override
Definition: FrameLib_Multistream.h:221
void blockUpdate(const double *const *ins, double **outs, unsigned long blockSize) override
Definition: FrameLib_Multistream.h:180
const FrameLib_Parameters::Serial * getSerialised() override
Definition: FrameLib_Multistream.h:129
ConnectionResult addConnection(Connection connection, unsigned long inIdx)
Definition: FrameLib_Object.h:254
void clearAllocator()
Definition: FrameLib_Object.h:406
std::string audioInfo(unsigned long idx, bool verbose) override
Definition: FrameLib_Multistream.h:240
std::string objectInfo(bool verbose) override
Definition: FrameLib_Multistream.h:236
a template class for providing multi-stream support to any FrameLib_Block class.
Definition: FrameLib_Multistream.h:124
FrameLib_Context getContext() const
Definition: FrameLib_Object.h:208
virtual ~FrameLib_Multistream()
Definition: FrameLib_Multistream.h:53
void clearOrderingConnections()
Definition: FrameLib_Object.h:280
FrameLib_Multistream(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, unsigned long nStreams, unsigned long nIns, unsigned long nOuts)
Definition: FrameLib_Multistream.h:44
bool supportsOrderingConnections() const
Definition: FrameLib_Object.h:337
virtual void reset(double samplingRate, unsigned long maxBlockSize)=0
virtual const FrameLib_Parameters::Serial * getSerialised()=0
FrameLib_Object< FrameLib_Block >::Connection BlockConnection
Definition: FrameLib_Multistream.h:34
FrameLib_Multistream & operator=(const FrameLib_Multistream &)=delete
FrameType outputType(unsigned long idx) const override
Definition: FrameLib_Multistream.h:246
size_t blockSize(void *ptr)
Definition: FrameLib_Memory.cpp:23
void enableOrderingConnections()
Definition: FrameLib_Object.h:391
const double * getFixedInput(unsigned long idx, unsigned long *size) override
Definition: FrameLib_Multistream.h:173
FrameType inputType(unsigned long idx) const override
Definition: FrameLib_Multistream.h:245
unsigned long getNumOrderingConnections() const
Definition: FrameLib_Object.h:338
virtual std::string audioInfo(unsigned long idx, bool verbose=false)
Definition: FrameLib_Object.h:243
std::string inputInfo(unsigned long idx, bool verbose) override
Definition: FrameLib_Multistream.h:237
void setIO(unsigned long nIns, unsigned long nOuts, unsigned long nAudioChans=0)
Definition: FrameLib_Object.h:381
FrameLib_Multistream(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, unsigned long nStreams)
Definition: FrameLib_Multistream.h:48
unsigned long getNumAudioOuts() const
Definition: FrameLib_Object.h:219
an extension of Serial that manages its own resizable memory.
Definition: FrameLib_Parameters.h:250
void setFixedInput(unsigned long idx, double *input, unsigned long size) override
Definition: FrameLib_Multistream.h:164
FrameType
Definition: FrameLib_Types.h:54
static const char * formatInfo(const char *verboseStr, const char *briefStr, bool verbose)
Definition: FrameLib_Object.h:418
unsigned long getOrderingConnectionNumChans(unsigned long idx)
Definition: FrameLib_Multistream.cpp:22
a abstract class proving multi-stream connnections and the means to the number of streams in a networ...
Definition: FrameLib_Multistream.h:29
void autoOrderingConnections() override
Definition: FrameLib_Multistream.h:252
unsigned long getNumStreams()
Definition: FrameLib_Multistream.h:66
typename FrameLib_Queueable< FrameLib_Multistream >::Queue Queue
Definition: FrameLib_Object.h:133
BlockConnection getOrderingConnectionChan(unsigned long idx, unsigned long chan)
Definition: FrameLib_Multistream.cpp:29
unsigned long getNumIns() const
Definition: FrameLib_Object.h:216
std::string outputInfo(unsigned long idx, bool verbose) override
Definition: FrameLib_Multistream.h:238